package org.example.model;

import java.util.*;
import java.util.stream.Collectors;

// 光照强度分级枚举
enum LightCondition {
    PITCH_DARK("<10 lux (极暗)"),
    DARK("10-50 lux (昏暗)"),
    LOW_LIGHT("50-200 lux (低光)"),
    NORMAL("200-1000 lux (正常)"),
    BRIGHT(">1000 lux (明亮)");

    private final String description;

    LightCondition(String description) {
        this.description = description;
    }

    public String getDescription() {
        return description;
    }
}

// 传感器类型枚举
enum SensorType {
    MILLIMETER_WAVE("毫米波"),
    LIDAR("激光雷达"),
    CAMERA("视觉"),
    ACOUSTIC("声纹");

    private final String description;

    SensorType(String description) {
        this.description = description;
    }

    public String getDescription() {
        return description;
    }
}

// 风险等级枚举
enum RiskLevel {
    NONE, LOW, MEDIUM, HIGH
}

// 传感器数据类（Java 8无record，用普通类替代）
class SensorData {
    private final SensorType type;
    private final float confidence;  // 0-1
    private final Float distance;    // 米，可为null
    private final Float speed;       // m/s，可为null
    private final Float frequency;   // Hz，可为null
    private final Float imageQuality; // 0-1，可为null

    public SensorData(SensorType type, float confidence, Float distance, Float speed, Float frequency, Float imageQuality) {
        this.type = type;
        this.confidence = confidence;
        this.distance = distance;
        this.speed = speed;
        this.frequency = frequency;
        this.imageQuality = imageQuality;
    }

    public SensorType getType() { return type; }
    public float getConfidence() { return confidence; }
    public Float getDistance() { return distance; }
    public Float getSpeed() { return speed; }
    public Float getFrequency() { return frequency; }
    public Float getImageQuality() { return imageQuality; }
}

// 预处理后的传感器数据类
class ProcessedSensorData {
    SensorType type;
    float rawConfidence;
    float effectiveConfidence;
    boolean isValid;
    Map<String, String> details;

    public ProcessedSensorData(SensorType type) {
        this.type = type;
        this.details = new HashMap<>();
    }

    public SensorType getType() { return type; }
    public float getRawConfidence() { return rawConfidence; }
    public float getEffectiveConfidence() { return effectiveConfidence; }
    public boolean isValid() { return isValid; }
    public Map<String, String> getDetails() { return details; }
}

// 检测结果类
class DetectionResult {
    String riskLevel;
    float totalScore;
    String lightCondition;
    List<String> activeSensors;
    List<String> explanations;
    Map<String, SensorDetail> sensorDetails;
    Map<String, Double> thresholds;

    public DetectionResult() {
        this.activeSensors = new ArrayList<>();
        this.explanations = new ArrayList<>();
        this.sensorDetails = new HashMap<>();
        this.thresholds = new HashMap<>();
    }

    public static class SensorDetail {
        float confidence;
        float weight;
        Map<String, String> details;

        public SensorDetail() {
            this.details = new HashMap<>();
        }

        public float getConfidence() { return confidence; }
        public float getWeight() { return weight; }
        public Map<String, String> getDetails() { return details; }
    }

    public void setRiskLevel(String riskLevel) { this.riskLevel = riskLevel; }
    public void setTotalScore(float totalScore) { this.totalScore = totalScore; }
    public void setLightCondition(String lightCondition) { this.lightCondition = lightCondition; }
    public List<String> getActiveSensors() { return activeSensors; }
    public List<String> getExplanations() { return explanations; }
    public Map<String, SensorDetail> getSensorDetails() { return sensorDetails; }
    public Map<String, Double> getThresholds() { return thresholds; }
}

public class LightAwareDroneDetector {
    // 传感器权重配置（根据不同光照条件）
    private final Map<LightCondition, Map<SensorType, Double>> weightConfig;

    // 决策阈值配置
    private final Map<RiskLevel, Double> thresholds;

    public LightAwareDroneDetector() {
        // 初始化权重配置（Java 8不支持EnumMap.of()，手动put）
        weightConfig = new EnumMap<>(LightCondition.class);

        // 极暗条件下的权重
        Map<SensorType, Double> pitchDarkWeights = new EnumMap<>(SensorType.class);
        pitchDarkWeights.put(SensorType.MILLIMETER_WAVE, 0.4);
        pitchDarkWeights.put(SensorType.LIDAR, 0.3);
        pitchDarkWeights.put(SensorType.CAMERA, 0.0);
        pitchDarkWeights.put(SensorType.ACOUSTIC, 0.3);
        weightConfig.put(LightCondition.PITCH_DARK, pitchDarkWeights);

        // 昏暗条件下的权重
        Map<SensorType, Double> darkWeights = new EnumMap<>(SensorType.class);
        darkWeights.put(SensorType.MILLIMETER_WAVE, 0.4);
        darkWeights.put(SensorType.LIDAR, 0.3);
        darkWeights.put(SensorType.CAMERA, 0.1);
        darkWeights.put(SensorType.ACOUSTIC, 0.2);
        weightConfig.put(LightCondition.DARK, darkWeights);

        // 低光条件下的权重
        Map<SensorType, Double> lowLightWeights = new EnumMap<>(SensorType.class);
        lowLightWeights.put(SensorType.MILLIMETER_WAVE, 0.3);
        lowLightWeights.put(SensorType.LIDAR, 0.3);
        lowLightWeights.put(SensorType.CAMERA, 0.2);
        lowLightWeights.put(SensorType.ACOUSTIC, 0.2);
        weightConfig.put(LightCondition.LOW_LIGHT, lowLightWeights);

        // 正常光照条件下的权重
        Map<SensorType, Double> normalWeights = new EnumMap<>(SensorType.class);
        normalWeights.put(SensorType.MILLIMETER_WAVE, 0.25);
        normalWeights.put(SensorType.LIDAR, 0.25);
        normalWeights.put(SensorType.CAMERA, 0.35);
        normalWeights.put(SensorType.ACOUSTIC, 0.15);
        weightConfig.put(LightCondition.NORMAL, normalWeights);

        // 明亮条件下的权重
        Map<SensorType, Double> brightWeights = new EnumMap<>(SensorType.class);
        brightWeights.put(SensorType.MILLIMETER_WAVE, 0.2);
        brightWeights.put(SensorType.LIDAR, 0.2);
        brightWeights.put(SensorType.CAMERA, 0.5);
        brightWeights.put(SensorType.ACOUSTIC, 0.1);
        weightConfig.put(LightCondition.BRIGHT, brightWeights);

        // 初始化阈值配置
        thresholds = new EnumMap<>(RiskLevel.class);
        thresholds.put(RiskLevel.HIGH, 0.85);
        thresholds.put(RiskLevel.MEDIUM, 0.7);
        thresholds.put(RiskLevel.LOW, 0.55);
    }

    /**
     * 根据光照强度分类
     */
    private LightCondition classifyLight(float lux) {
        if (lux < 10) {
            return LightCondition.PITCH_DARK;
        } else if (lux < 50) {
            return LightCondition.DARK;
        } else if (lux < 200) {
            return LightCondition.LOW_LIGHT;
        } else if (lux < 1000) {
            return LightCondition.NORMAL;
        } else {
            return LightCondition.BRIGHT;
        }
    }

    /**
     * 预处理单个传感器数据
     */
    private ProcessedSensorData preprocessSensor(SensorData data) {
        ProcessedSensorData result = new ProcessedSensorData(data.getType());
        result.rawConfidence = data.getConfidence();
        result.effectiveConfidence = data.getConfidence();

        // Java 8不支持switch表达式，用传统switch
        switch (data.getType()) {
            case MILLIMETER_WAVE:
                // 毫米波雷达处理
                float speed = data.getSpeed() != null ? data.getSpeed() : 0.0f;
                float speedFactor = (float) Math.max(0, Math.min(1, Math.abs(speed - 10) / 15.0));

                float distance = data.getDistance() != null ? data.getDistance() : 0.0f;
                float distFactor = (float) Math.max(0, Math.min(1, 1 / (distance + 0.1)));

                result.effectiveConfidence = 0.6f * data.getConfidence() + 0.2f * speedFactor + 0.2f * distFactor;
                result.isValid = distance < 100;  // 超过100米认为不可靠

                result.details.put("speed", String.format("%.1fm/s", speed));
                result.details.put("distance", String.format("%.1fm", distance));
                break;

            case LIDAR:
                // 激光雷达处理
                float lidarDistance = data.getDistance() != null ? data.getDistance() : 0.0f;
                float lidarDistFactor = (float) Math.max(0, Math.min(1, 1 / (lidarDistance + 0.1)));

                result.effectiveConfidence = 0.8f * data.getConfidence() + 0.2f * lidarDistFactor;
                result.isValid = lidarDistance < 80;

                result.details.put("distance", String.format("%.1fm", lidarDistance));
                break;

            case CAMERA:
                // 摄像头处理
                float quality = data.getImageQuality() != null ? data.getImageQuality() : 0.5f;
                result.effectiveConfidence = 0.7f * data.getConfidence() + 0.3f * quality;
                result.isValid = quality > 0.3;  // 图像质量过低时丢弃

                result.details.put("quality", String.format("%.2f", quality));
                break;

            case ACOUSTIC:
                // 声纹处理
                float frequency = data.getFrequency() != null ? data.getFrequency() : 0.0f;
                float freqFactor = 1 - (float) Math.max(0, Math.min(1, Math.abs(frequency - 150) / 100.0));

                result.effectiveConfidence = 0.4f * data.getConfidence() + 0.6f * freqFactor;
                result.isValid = frequency > 100 && frequency < 300;

                result.details.put("frequency", String.format("%.1fHz", frequency));
                break;
        }

        return result;
    }

    /**
     * 执行无人机检测
     */
    public DetectionResult detect(List<SensorData> sensorData, float lightIntensity) {
        DetectionResult result = new DetectionResult();

        // 1. 确定当前光照条件
        LightCondition lightCond = classifyLight(lightIntensity);
        result.setLightCondition(lightCond.name());
        System.out.printf("当前光照条件: %s (%f lux)%n", lightCond.name(), lightIntensity);

        // 2. 预处理所有传感器数据（Java 8 Stream操作）
        List<ProcessedSensorData> processed = sensorData.stream()
                .map(this::preprocessSensor)
                .filter(ProcessedSensorData::isValid)
                .collect(Collectors.toList());

        // 3. 计算加权综合得分
        float totalScore = 0.0f;
        Map<SensorType, Double> weights = weightConfig.get(lightCond);

        for (ProcessedSensorData sensor : processed) {
            double weight = weights.getOrDefault(sensor.getType(), 0.0);
            double contribution = weight * sensor.getEffectiveConfidence();
            totalScore += contribution;

            // 记录解释信息
            result.getExplanations().add(String.format(
                    "%s: 原始置信度=%.2f, 处理后=%.2f, 权重=%.2f, 贡献=%.2f",
                    sensor.getType().getDescription(),
                    sensor.getRawConfidence(),
                    sensor.getEffectiveConfidence(),
                    weight,
                    contribution
            ));

            // 添加传感器详情
            DetectionResult.SensorDetail detail = new DetectionResult.SensorDetail();
            detail.confidence = sensor.getEffectiveConfidence();
            detail.weight = (float) weight;
            detail.details.putAll(sensor.getDetails());
            result.getSensorDetails().put(sensor.getType().getDescription(), detail);
            result.getActiveSensors().add(sensor.getType().getDescription());
        }

        // 保留三位小数
        result.setTotalScore((float) Math.round(totalScore * 1000) / 1000);

        // 4. 风险等级判定
        RiskLevel risk = RiskLevel.NONE;
        if (totalScore >= thresholds.get(RiskLevel.HIGH)) {
            risk = RiskLevel.HIGH;
        } else if (totalScore >= thresholds.get(RiskLevel.MEDIUM)) {
            risk = RiskLevel.MEDIUM;
        } else if (totalScore >= thresholds.get(RiskLevel.LOW)) {
            risk = RiskLevel.LOW;
        }
        result.setRiskLevel(risk.name());

        // 5. 记录阈值信息
        thresholds.forEach((k, v) -> result.getThresholds().put(k.name(), v));

        return result;
    }

    // Java 8不支持String.repeat()，手动实现重复字符串
    private static String repeat(String s, int n) {
        if (s == null || n <= 0) return "";
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < n; i++) {
            sb.append(s);
        }
        return sb.toString();
    }

    public static void main(String[] args) {
        // 初始化检测器
        LightAwareDroneDetector detector = new LightAwareDroneDetector();

        // 模拟不同光照条件下的测试
        List<Object[]> testCases = Arrays.asList(
                // (光照强度, 传感器数据列表)
                new Object[]{5.0f, Arrays.asList(
                        new SensorData(SensorType.MILLIMETER_WAVE, 0.85f, 45.0f, 12.0f, null, null),
                        new SensorData(SensorType.LIDAR, 0.75f, 40.0f, null, null, null),
                        new SensorData(SensorType.CAMERA, 0.3f, null, null, null, 0.1f),
                        new SensorData(SensorType.ACOUSTIC, 0.65f, null, null, 160.0f, null)
                )},
                new Object[]{300.0f, Arrays.asList(
                        new SensorData(SensorType.MILLIMETER_WAVE, 0.7f, 60.0f, 8.0f, null, null),
                        new SensorData(SensorType.LIDAR, 0.8f, 55.0f, null, null, null),
                        new SensorData(SensorType.CAMERA, 0.9f, null, null, null, 0.8f),
                        new SensorData(SensorType.ACOUSTIC, 0.5f, null, null, 140.0f, null)
                )},
                new Object[]{1500.0f, Arrays.asList(
                        new SensorData(SensorType.MILLIMETER_WAVE, 0.6f, 70.0f, 15.0f, null, null),
                        new SensorData(SensorType.LIDAR, 0.7f, 65.0f, null, null, null),
                        new SensorData(SensorType.CAMERA, 0.95f, null, null, null, 0.9f),
                        new SensorData(SensorType.ACOUSTIC, 0.4f, null, null, 180.0f, null)
                )}
        );

        for (Object[] testCase : testCases) {
            float lux = (float) testCase[0];
            List<SensorData> sensors = (List<SensorData>) testCase[1];

            System.out.println("\n" + repeat("=", 50));
            System.out.printf("测试案例 - 光照强度: %f lux%n", lux);

            DetectionResult result = detector.detect(sensors, lux);

            System.out.println("\n[检测结果]");
            System.out.printf("风险等级: %s%n", result.riskLevel);
            System.out.printf("综合得分: %.2f (阈值: %s)%n",
                    result.totalScore, result.thresholds);
            System.out.printf("有效传感器: %s%n", result.activeSensors);

            System.out.println("\n[决策解释]");
            result.explanations.forEach(exp -> System.out.printf("- %s%n", exp));

            System.out.println("\n[传感器详情]");
            result.sensorDetails.forEach((name, detail) -> {
                System.out.printf("%s: 置信度=%.2f, 权重=%.2f%n",
                        name, detail.confidence, detail.weight);
                detail.details.forEach((k, v) -> System.out.printf("  - %s: %s%n", k, v));
            });
        }
    }
}